#ifndef NEWTON_H
#define NEWTON_H

#include <cassert>
#include <stdint.h>

namespace NumericalAnalysis
{
    // Input data of the Newton method
    // It contains:
    // (1) Estimation function.
    // (2) Derived of the estimation function.
    // (3) Initial estimation (X0).
    // (4) Max number of iterations allowed.
    // (5) Stop bound.  
    struct NewtonInputData
    {
    	NewtonInputData(double (*estimationFunction) (const double x) = 0, double (*derived) (const double x) = 0, 
    		const double initialEstimation = 0.0, const uint32_t maxIterations = 0, const double stopBound = 0.0)
			: mEstimationFunction(estimationFunction)
			, mDerived(derived)
			, mInitialEstimation(initialEstimation)
			, mMaxIterations(maxIterations)
			, mStopBound(stopBound)
		{
			assert(estimationFunction && "NewtonInputData::NewtonInputData: NULL pointer");
			assert(derived && "NewtonInputData::NewtonInputData: NULL pointer");
		}

    	double (*mEstimationFunction) (const double x);
    	double (*mDerived) (const double x);
    	double mInitialEstimation;
    	uint32_t mMaxIterations;
    	double mStopBound;
    };    


    // Output data of the Newton method.
    // It contains:
    // (1) Iterations performed.
    // (2) Final estimation.
    // (3) Relative error (|XfinalEstimation - XpreviousEstimation| / |XfinalEstimation|)
    // (4) Absolute value of the valued final estimation by the estimation function.
    struct NewtonOutputData
    {
    	NewtonOutputData(const uint32_t finalIterationNumber = 0, const double finalEstimation = 0.0, const double relativeError = 0.0,
    		const double absOfValuedFinalEstimationByFunction = 0.0)
			: mFinalIterationNumber(finalIterationNumber)
			, mFinalEstimation(finalEstimation)
			, mRelativeError(relativeError)
			, mAbsOfValuedFinalEstimationByFunction(absOfValuedFinalEstimationByFunction)
		{

		}

    	uint32_t mFinalIterationNumber;
    	double mFinalEstimation;
    	double mRelativeError;
    	double mAbsOfValuedFinalEstimationByFunction;
    };

    // Performs the Newton method to estimate a value.
    // It takes a NewtonInputData and returns a NewtonOutputData.
    NewtonOutputData NewtonMethod(const NewtonInputData& inputData);
}

#endif // NEWTON_H
